package com.viu.technology.chat;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;

import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;


public class NoticeClient {

    private int port;

    public NoticeClient(int port) {
        this.port = port;
    }

    @PostConstruct
    public void connect() throws InterruptedException {

        //配置客户端NIO线程组
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    //TCP_NODELAY就是用于启用或关于Nagle算法。如果要求高实时性，有数据发送时就马上发送，
                    // 就将该选项设置为true关闭Nagle算法；如果要减少发送次数减少网络交互，就设置为false等累积一定大小后再发送。默认为false。
                    .option(ChannelOption.TCP_NODELAY,true )
                    .remoteAddress(new InetSocketAddress("127.0.0.1",port))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
                            socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                            //将接收到的对象转换为字符串
                            /*socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2));
                            socketChannel.pipeline().addLast(new LengthFieldPrepender(2));*/
                            socketChannel.pipeline().addLast(new StringDecoder());
                            socketChannel.pipeline().addLast(new NoticeClientHandler());
                            //第一个参数 60 表示读操作空闲时间,第二个参数 20 表示写操作空闲时间,第三个参数 60*10 表示读写操作空闲时间,第四个参数 单位/秒
                            socketChannel.pipeline().addLast("ping", new IdleStateHandler(60, 5, 60 * 10, TimeUnit.SECONDS));
                        }
                    });
            //发起异步连接操作
            ChannelFuture f = b.connect().sync();
            //等待客户端链路关闭
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }

    }


    public static void main(String args[]) throws InterruptedException {
        int port = 10203;
        if (args != null && args.length > 0) {
            port = Integer.valueOf(args[0]);
        }
        //new NoticeClient(port).connect();

        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                try {
                    new NoticeClient(10203).connect();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        for (int i = 0; i < 100; i++) {
            new Thread(runnable).start();
        }
        
        Thread.sleep(100000);
    }

}
